package com.example.tongyao.utils.token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.example.tongyao.system.entity.SysUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * TongYao2.0 >>> 【com.example.tongyao.system.utils】
 * Token工具类
 *
 * @author: tongyao
 * @since: 2021-08-01 17:58
 */
@Service
public class TokenUtil {

    //过期时间
    @Value("${token.expireDate}")
    private int EXPIREDATE;

    //密钥
    @Value("${token.secret}")
    private String SECRET;

    public String createToken(SysUser user) {

        //过期时间
        long EXPIRE_TIME = EXPIREDATE * 60 * 1000;
        Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);

        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create()
                .withHeader(map)        //添加主体

                //可以将基本信息放到claims中
                .withClaim("userId", user.getUserId())
                .withClaim("userName", user.getUsername())
                .withExpiresAt(expireDate)
                .withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(SECRET));

        return token;
    }

    //解析token多实体属性
    public Map<String, Claim> parsingToken(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            // 验证 token ，包括是否过期
            jwt = verifier.verify(token);
        } catch (JWTDecodeException e){
            throw new RuntimeException("令牌签名解析用户信息失败！");
        }catch (JWTVerificationException e) {
            throw new RuntimeException("您的令牌无效！");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("令牌解析出现未知错误！");
        }
        return jwt.getClaims();
    }
}